import base64
import os
from io import FileIO

from Crypto.Hash import SHA256
from Crypto.Util.asn1 import DerSequence, DerObjectId, DerNull, DerOctetString
from Crypto.Util.number import ceil_div
from cryptography import x509
from setuptools.command.setopt import config_file

cert_consumer = None
base_dir = os.path.dirname(os.path.abspath(__file__))
"""
# power.conf 的配置格式为EQUAL,x,y,z->fakeResult，只配置第一个 result 即可。
#  "x:证书的签名密文；sign"
#  "y:指数；exponent"
#  "z：jetbrains内置root证书的公钥的模；modulus"
#  "fakeResult：证书签名（sh256摘要后的明文）ASN.1格式再进行填充。 fakeResult")
"""


# 通过上一步我们自己生成的证书，生成 sign
def get_sign():
    crt_path = os.path.join(base_dir, '0/ca.crt')
    with open(crt_path) as prifileCrt:
        certBase64 = prifileCrt.read()
        certBase64 = certBase64.replace('-----BEGIN CERTIFICATE-----', '')
        certBase64 = certBase64.replace('-----END CERTIFICATE-----', '')
        certBase64 = certBase64.replace('\n', '')
        global cert_consumer
        cert_consumer = x509.load_der_x509_certificate(base64.b64decode(certBase64))
        sign = int.from_bytes(cert_consumer.signature, byteorder="big", )
        print(f"sign:{sign}")
        return sign


# 这是一个默认值不需要修改，RSA的指数为65537，生成 exponent
def get_exponent():
    exponent = 65537
    print(f"exponent:{exponent}")
    return exponent


# 获取jetbrains内置证书的模，生成modulus
# ja-netfilter已经做了替换，让我们的签名始终正确
def get_modulus():
    # https://github.com/JetBrains/marketplace-makemecoffee-plugin/blob/master/src/main/java/com/company/license/CheckLicense.java
    certBase64 = get_cert_jetbrains()
    cert_jetbrains = x509.load_der_x509_certificate(base64.b64decode(certBase64))
    public_key = cert_jetbrains.public_key()
    modulus = public_key.public_numbers().n
    print(f"modulus:{modulus}")
    return modulus


# 计算验证结果，直接将自己生成的证书作为返回只，所以会始终正确，生成result
def get_fake_result():
    public_key = cert_consumer.public_key()
    modBits = public_key.key_size
    digest_cert = SHA256.new(cert_consumer.tbs_certificate_bytes)
    fakeResult = int.from_bytes(pkcs15_encode(digest_cert, ceil_div(modBits, 8)), byteorder='big', signed=False)
    print(f"result:{fakeResult}")
    return fakeResult


# 附加函数区域，PKCS15的补码规则
def pkcs15_encode(msg_hash, emLen, with_hash_parameters=True):
    digest_algo = DerSequence([DerObjectId(msg_hash.oid).encode()])
    if with_hash_parameters:
        digest_algo.append(DerNull().encode())
    digest_info = DerSequence([
        digest_algo.encode(),
        DerOctetString(msg_hash.digest()).encode()
    ]).encode()
    min_length = len(digest_info) + 11
    if emLen < min_length:
        raise TypeError(f"Selected hash algorithm has a too long digest ({len(msg_hash.digest())} bytes).")
    padding_length = emLen - len(digest_info) - 3
    padding = b'\xFF' * padding_length
    return b'\x00\x01' + padding + b'\x00' + digest_info


# 这里的秘钥是从jetbrains官网下载的，可以从github下载
# https://plugins.jetbrains.com/docs/marketplace/add-marketplace-license-verification-calls-to-the-plugin-code.html
# https://github.com/JetBrains/marketplace-makemecoffee-plugin/blob/master/src/main/java/com/company/license/CheckLicense.java
def get_cert_jetbrains():
    certBase64_jetbrains = '''MIIFOzCCAyOgAwIBAgIJANJssYOyg3nhMA0GCSqGSIb3DQEBCwUAMBgxFjAUBgNV\n
    BAMMDUpldFByb2ZpbGUgQ0EwHhcNMTUxMDAyMTEwMDU2WhcNNDUxMDI0MTEwMDU2\n
    WjAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMIICIjANBgkqhkiG9w0BAQEFAAOC\n
    Ag8AMIICCgKCAgEA0tQuEA8784NabB1+T2XBhpB+2P1qjewHiSajAV8dfIeWJOYG\n
    y+ShXiuedj8rL8VCdU+yH7Ux/6IvTcT3nwM/E/3rjJIgLnbZNerFm15Eez+XpWBl\n
    m5fDBJhEGhPc89Y31GpTzW0vCLmhJ44XwvYPntWxYISUrqeR3zoUQrCEp1C6mXNX\n
    EpqIGIVbJ6JVa/YI+pwbfuP51o0ZtF2rzvgfPzKtkpYQ7m7KgA8g8ktRXyNrz8bo\n
    iwg7RRPeqs4uL/RK8d2KLpgLqcAB9WDpcEQzPWegbDrFO1F3z4UVNH6hrMfOLGVA\n
    xoiQhNFhZj6RumBXlPS0rmCOCkUkWrDr3l6Z3spUVgoeea+QdX682j6t7JnakaOw\n
    jzwY777SrZoi9mFFpLVhfb4haq4IWyKSHR3/0BlWXgcgI6w6LXm+V+ZgLVDON52F\n
    LcxnfftaBJz2yclEwBohq38rYEpb+28+JBvHJYqcZRaldHYLjjmb8XXvf2MyFeXr\n
    SopYkdzCvzmiEJAewrEbPUaTllogUQmnv7Rv9sZ9jfdJ/cEn8e7GSGjHIbnjV2ZM\n
    Q9vTpWjvsT/cqatbxzdBo/iEg5i9yohOC9aBfpIHPXFw+fEj7VLvktxZY6qThYXR\n
    Rus1WErPgxDzVpNp+4gXovAYOxsZak5oTV74ynv1aQ93HSndGkKUE/qA/JECAwEA\n
    AaOBhzCBhDAdBgNVHQ4EFgQUo562SGdCEjZBvW3gubSgUouX8bMwSAYDVR0jBEEw\n
    P4AUo562SGdCEjZBvW3gubSgUouX8bOhHKQaMBgxFjAUBgNVBAMMDUpldFByb2Zp\n
    bGUgQ0GCCQDSbLGDsoN54TAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkq\n
    hkiG9w0BAQsFAAOCAgEAjrPAZ4xC7sNiSSqh69s3KJD3Ti4etaxcrSnD7r9rJYpK\n
    BMviCKZRKFbLv+iaF5JK5QWuWdlgA37ol7mLeoF7aIA9b60Ag2OpgRICRG79QY7o\n
    uLviF/yRMqm6yno7NYkGLd61e5Huu+BfT459MWG9RVkG/DY0sGfkyTHJS5xrjBV6\n
    hjLG0lf3orwqOlqSNRmhvn9sMzwAP3ILLM5VJC5jNF1zAk0jrqKz64vuA8PLJZlL\n
    S9TZJIYwdesCGfnN2AETvzf3qxLcGTF038zKOHUMnjZuFW1ba/12fDK5GJ4i5y+n\n
    fDWVZVUDYOPUixEZ1cwzmf9Tx3hR8tRjMWQmHixcNC8XEkVfztID5XeHtDeQ+uPk\n
    X+jTDXbRb+77BP6n41briXhm57AwUI3TqqJFvoiFyx5JvVWG3ZqlVaeU/U9e0gxn\n
    8qyR+ZA3BGbtUSDDs8LDnE67URzK+L+q0F2BC758lSPNB2qsJeQ63bYyzf0du3wB\n
    /gb2+xJijAvscU3KgNpkxfGklvJD/oDUIqZQAnNcHe7QEf8iG2WqaMJIyXZlW3me\n
    0rn+cgvxHPt6N4EBh5GgNZR4l0eaFEV+fxVsydOQYo1RIyFMXtafFBqQl6DDxujl\n
    FeU3FZ+Bcp12t7dlM4E0/sS1XdL47CfGVj4Bp+/VbF862HmkAbd7shs7sDQkHbU=\n'''
    format_path = os.path.join(base_dir, "2/format.json")
    with open(format_path, 'a') as file:
        config_file = file.read()
        if config_file is not None:
            certBase64_jetbrains = config_file
    return certBase64_jetbrains


def gen_power_conf():
    sign_one = get_sign()
    exponent_one = get_exponent()
    modulus_one = get_modulus()
    fakeResult = get_fake_result()
    print(f"EQUAL,{sign_one},{exponent_one},{modulus_one}->{fakeResult}")
    return f"EQUAL,{sign_one},{exponent_one},{modulus_one}->{fakeResult}"


# power.conf 的配置格式为EQUAL,x,y,z->fakeResult，只配置第一个 result 即可
#  EQUAL,x,y,z->fakeResult ，符合x.modpow(y,z)=fakeResult,
#  就是匹配x,y,z三个参数, 并替换模幂运算结果为fakeResult, "
#  "x:证书的签名密文；sign"
#  "y:指数；exponent"
#  "z：jetbrains内置root证书的公钥的模；modulus"
#  "fakeResult：证书签名（sh256摘要后的明文）ASN.1格式再进行填充。 fakeResult")
if __name__ == '__main__':
    sign_one = get_sign()
    exponent_one = get_exponent()
    modulus_one = get_modulus()
    fakeResult = get_fake_result()
    print("\n\n 将生成的字符串复制到power.conf中result区域，并替换掉原来的配置 \n\n")
    print(f"EQUAL,{sign_one},{exponent_one},{modulus_one}->{fakeResult}")
    power_path = os.path.join(base_dir, "1/power.conf")
    with open(power_path, "w") as f:
        f.write("[Result]\n")
        f.write(f"EQUAL,{sign_one},{exponent_one},{modulus_one}->{fakeResult}")
